﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#include "CThread.h"
#include "CThreadManager.h"

namespace UX_STL
{
namespace UXTypesExt
{
	
#ifdef _UXS_STL_CONFIGURATION_H
	IThread *	_s_pCurrentThread	= null;
#endif



//--------------------------- CThread -----------------------------//
/*
=================================================
	конструктор
=================================================
*/
	CThread::CThread(): IThread(e_thread::THREAD_0), _bLooping(false)
	{
		_aOpQueue.Reserve( 50 );
		_uEmploymentRate = 0;
	}
	
/*
=================================================
	деструктор
=================================================
*/
	CThread::~CThread()
	{
		THREADMAN()->RemoveThread( this );

		Exit();
	}
	
/*
=================================================
	цикл обработки задач
=================================================
*/
	int CThread::_Loop()
	{
		_bLooping = true;

		while ( _bLooping )
		{
			_sCSLockQueue.Lock();

			if ( !_aOpQueue.Empty() )
			{
				IThreadOp	*p_op = null;
				
				p_op = _aOpQueue.Front();
				_aOpQueue.PopFront();

				_sCSLockQueue.Unlock();
			
				p_op->Do();
			}
			else
			{
				_sCSLockQueue.Unlock();
				TPlatform::Yield();
			}
		}
		return 0;
	}
	
/*
=================================================
	запистить поток
=================================================
*/
	bool CThread::Run(/*e_thread_priority::type ePriority*/)
	{
		struct TThreadProc
		{
			static void Proc (void *pParam) { ((CThread *)pParam)->_Loop(); }
		};

		CHECK_ERR( _sThread.Create( &TThreadProc::Proc, this ) );
		//_sThread.SetPriority( ePriority );
		
		THREADMAN()->AddThread( this );
		return true;
	}
	
/*
=================================================
	добавить задачу в очередь
=================================================
*/
	bool CThread::Push(IThreadOp *pOp, bool bHighPriority)
	{
		if ( pOp == null )
			return false;
		
		//if ( _bLooping )
		{
			_sCSLockQueue.Lock();

			if ( bHighPriority )	_aOpQueue.PushFront( pOp );
			else					_aOpQueue.PushBack( pOp );
			
			_uEmploymentRate = _aOpQueue.Count();

			_sCSLockQueue.Unlock();
		}
		//else
		//{
		//	WARNING( "" );
		//	pOp->Do();
		//}

		return true;
	}
	
/*
=================================================
	выход из потока (цикла обработки задач)
=================================================
*/
	void CThread::Exit()
	{
		_bLooping = false;
		_sThread.Wait();
		_sThread.Delete();
	}
	
/*
=================================================
	приостановить поток
=================================================
*/
	bool CThread::Pause()
	{
		return false;
		//return ( _bLooping ? _sThread.Suspend() : false );
	}
	
/*
=================================================
	возобновить поток
=================================================
*/
	bool CThread::Resume()
	{
		return false;
		//return ( _bLooping ? _sThread.Resume() : false );
	}
	
/*
=================================================
	является ли текущим
=================================================
*/
	bool CThread::IsCurrent()
	{
		return !_sThread.IsValid() or _sThread.IsCurrent();
	}


	
//------------------------ CWindowThread --------------------------//
/*
=================================================
	конструктор
=================================================
*/
	CWindowThread::CWindowThread(CWindow *pWnd): IThread(e_thread::RENDER_WINDOW)
	{
		pWnd->AddUpdater( this );
		_aOpQueue.Reserve( 50 );
		_uEmploymentRate = 0;
		THREADMAN()->AddThread( this );
	}
	
/*
=================================================
	детсруктор
=================================================
*/
	CWindowThread::~CWindowThread()
	{
		THREADMAN()->RemoveThread( this );
		Exit();
	}
	
/*
=================================================
	добавить задачу в очередь
=================================================
*/
	bool CWindowThread::Push(IThreadOp *pOp, bool bHighPriority)
	{
		if ( pOp == null )
			return false;
	
		SCOPELOCK( _sCSLockQueue );

		if ( bHighPriority )	_aOpQueue.PushFront( pOp );
		else					_aOpQueue.PushBack( pOp );
			
		_uEmploymentRate = _aOpQueue.Count();
		return true;
	}
	
/*
=================================================
	выход из потока
=================================================
*/
	void CWindowThread::Exit()
	{
		_pWindow->Quit();
		_sThread.Wait();
		_sThread.Delete();
	}
		
/*
=================================================
	обработка задач при обновлении (перерисовке) окна
=================================================
*/
	void CWindowThread::OnUpdate(CWindow *)
	{
		_sCSLockQueue.Lock();

		if ( !_aOpQueue.Empty() )
		{
			IThreadOp	*p_op = null;
				
			p_op = _aOpQueue.Front();
			_aOpQueue.PopFront();

			_sCSLockQueue.Unlock();
			
			p_op->Do();
		}
		else
			_sCSLockQueue.Unlock();
	}
	
/*
=================================================
	приостановить поток
=================================================
*/
	bool CWindowThread::Pause()
	{
		return false;
		//return _sThread.Suspend();
	}
	
/*
=================================================
	возобновить поток
=================================================
*/
	bool CWindowThread::Resume()
	{
		return false;
		//return _sThread.Resume();
	}
	
/*
=================================================
	является ли текущим
=================================================
*/
	bool CWindowThread::IsCurrent()
	{
		return !_sThread.IsValid() or _sThread.IsCurrent();
	}


	
//---------------------- CMainWindowThread ------------------------//
/*
=================================================
	контсруктор
=================================================
*/
	CMainWindowThread::CMainWindowThread(CWindow *pWnd): _pWindow(pWnd), IThread(e_thread::MAIN_WINDOW)
	{
		pWnd->AddUpdater( this );
		_aOpQueue.Reserve( 50 );
		_uEmploymentRate = 0;
		THREADMAN()->AddThread( this );
	}
	
/*
=================================================
	детсруктор
=================================================
*/
	CMainWindowThread::~CMainWindowThread()
	{
		THREADMAN()->RemoveThread( this );
		Exit();
	}
	
/*
=================================================
	добавить задачу в очередь
=================================================
*/
	bool CMainWindowThread::Push(IThreadOp *pOp, bool bHighPriority)
	{
		if ( pOp == null )
			return false;
		
		SCOPELOCK( _sCSLockQueue );

		if ( bHighPriority )	_aOpQueue.PushFront( pOp );
		else					_aOpQueue.PushBack( pOp );
			
		_uEmploymentRate = _aOpQueue.Count();
		return true;
	}
	
/*
=================================================
	выход из потока
=================================================
*/
	void CMainWindowThread::Exit()
	{
		_pWindow->Quit();
	}
		
/*
=================================================
	обработка задач при обновлении окна
=================================================
*/
	void CMainWindowThread::OnUpdate(CWindow *)
	{
		_sCSLockQueue.Lock();

		if ( !_aOpQueue.Empty() )
		{
			IThreadOp	*p_op = null;
				
			p_op = _aOpQueue.Front();
			_aOpQueue.PopFront();

			_sCSLockQueue.Unlock();
			
			p_op->Do();
		}
		else
			_sCSLockQueue.Unlock();
	}
	
/*
=================================================
	приостановить поток
=================================================
*/
	bool CMainWindowThread::Pause()
	{
		return false;
		//return _sThread.Suspend();
	}
	
/*
=================================================
	возобновить поток
=================================================
*/
	bool CMainWindowThread::Resume()
	{
		return false;
		//return _sThread.Resume();
	}
	
/*
=================================================
	является ли текущим
=================================================
*/
	bool CMainWindowThread::IsCurrent()
	{
		return !_sThread.IsValid() or _sThread.IsCurrent();
	}

//-------------------------------------------------------------------

}	// UXTypesExt
}	// UX_STL